//! Deck class definition

#include "include/Deck.h"
#include <assert.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <QDebug>
#include "include/Card.h"
#include <QMap>
#include <climits>

#include <QFile>

using namespace std;

Deck::Deck():
	m_changed(false)
{
	m_pUpdateMutex = new QMutex();
}

Deck::~Deck()
{
	delete m_pUpdateMutex;
}

Deck::Deck(const Deck& r)
{
	m_cardsMap = r.m_cardsMap;
	m_path = r.m_path;
	m_changed = r.m_changed;
	m_pUpdateMutex = new QMutex();
}

QDataStream &operator<<( QDataStream &stream, const Deck &data )
{
	stream << data.m_cardsMap.size();
	for (QMap<QUuid, Card*>::const_iterator it = data.m_cardsMap.begin(); it != data.m_cardsMap.end(); it++)
	{
		stream << it.key();
		Card* card = it.value();
		card->writeCurrentVer(stream);
	}
	return stream;
}


void Deck::readFromVer0(QDataStream &stream, int cardsCount)
{
	clear();
	QUuid uuid;
	Card card;
	for (int i = 0; i < cardsCount; i++)
	{
		stream >> uuid;
		card.readVer1(stream);
		m_cardsMap[uuid] = new Card(card);
	}
}

void Deck::readFromVer1(QDataStream &stream)
{
	qint32 cardsCount;
	stream >> cardsCount;
	readFromVer0(stream, cardsCount);
}


void Deck::readFromVer2(QDataStream &stream)
{
	qint32 cardsCount;
	stream >> cardsCount;

	clear();
	QUuid uuid;
	Card card;
	for (int i = 0; i < cardsCount; i++)
	{
		stream >> uuid;
		card.readVer2(stream);
		m_cardsMap[uuid] = new Card(card);
	}
}



void Deck::clear()
{
	foreach (QUuid uuid, m_cardsMap.keys())
	{
		delete m_cardsMap[uuid];
	}
	m_cardsMap.clear();
}


void Deck::addCard(Card* pCard)
{
	m_pUpdateMutex->lock();
	m_cardsMap[pCard->getUuid()] = pCard;
	m_pUpdateMutex->unlock();
}

void Deck::deleteCard(Card* pCard)
{
	QMap<QUuid, Card*>::iterator it = m_cardsMap.find(pCard->getUuid());
	if (it != m_cardsMap.end())
		m_cardsMap.erase(it);
}

size_t	Deck::size() const
{
	return m_cardsMap.size();
}

Card* Deck::getCard(const QUuid& uuid) const
{
	m_pUpdateMutex->lock();
	Card* pCard = *m_cardsMap.find(uuid);
	m_pUpdateMutex->unlock();
	return pCard;
}

void Deck::updateCard(Card* pCard)
{
	m_pUpdateMutex->lock();
	m_cardsMap[pCard->getUuid()] = pCard;
	m_pUpdateMutex->unlock();
}

void Deck::setPath(QString path)
{
	m_path = path;
}

QString Deck::getPath()
{
	return m_path;
}

int Deck::getLastDisplayed() const
{
	int lastDate = 0;
	for (QMap<QUuid, Card*>::const_iterator it = m_cardsMap.begin(); it != m_cardsMap.end(); it++)
	{
		int last = (*it)->getLastDisplayed();
		if (last > lastDate)
			lastDate = last;
	}
	if (lastDate == INT_MAX)
		return -1;

	return lastDate;
}

int Deck::getFirstDisplayed() const
{
	int firstDate = INT_MAX;
	for (QMap<QUuid, Card*>::const_iterator it = m_cardsMap.begin(); it != m_cardsMap.end(); it++)
	{
		int first = (*it)->getFirstDisplayed();
		if (first < firstDate)
			firstDate = first;
	}
	if (firstDate == INT_MAX)
		return -1;

	return firstDate;
}

int Deck::getAge() const
{
	return getLastDisplayed() - getFirstDisplayed();
}

bool Deck::hasChanged() const
{
	return m_changed;
}

void Deck::setSaved()
{
	m_changed = false;
}

bool Deck::hasCard(const QUuid& arUuid) const
{
	if (arUuid.isNull())
		return false;
	return m_cardsMap.find(arUuid) != m_cardsMap.end();
}
